package com.daffodil.core.dao.impl;

import java.util.Iterator;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import com.daffodil.core.dao.JpaDao;
import com.daffodil.core.dao.helper.DaoHelper;
import com.daffodil.core.entity.BaseEntity;
import com.daffodil.core.entity.Page;
import com.daffodil.core.exception.BusinessException;

/**
 * 
 * @author yweijian
 * @version 1.0
 * @description
 */
@Repository("longJpaDao")
public class LongJpaDaoImpl implements JpaDao<Long> {
	
	@Autowired
	private EntityManager entityManager;
	
	private static int DEFAULT_PAGE_NUM  = 1;
	
	private static int DEFAULT_PAGE_SIZE  = 9999;

	public Long save(BaseEntity<Long> entity) throws BusinessException {
		try {
			if (entity.getId() == null) {
				entity.setId(null);
			}
			this.entityManager.persist(entity);
			return entity.getId();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	public void delete(BaseEntity<Long> entity) throws BusinessException {
		try {
			this.entityManager.remove(this.entityManager.contains(entity) ? entity : this.entityManager.merge(entity));
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	public void delete(BaseEntity<Long>[] entitys) throws BusinessException {
		try {
			int j = entitys.length;
			for (int i = 0; i < j; i++) {
				BaseEntity<Long> entity = entitys[i];
				this.entityManager.remove(this.entityManager.contains(entity) ? entity : this.entityManager.merge(entity));
			}
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}
	
	public void delete(List<?> entitys) throws BusinessException {
		try {
			for (Object entity : entitys) {
				this.entityManager.remove(this.entityManager.contains(entity) ? entity : this.entityManager.merge(entity));
			}
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	public void delete(String hql) throws BusinessException {
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql);
			query.executeUpdate();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	public void delete(String hql, Object para) throws BusinessException {
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql);
			query.setParameter(0, para);
			query.executeUpdate();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	public void delete(String hql, List<Object> paras) throws BusinessException {
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql);
			DaoHelper.setQueryParas(query, paras);
			query.executeUpdate();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	@SuppressWarnings("unchecked")
	public void delete(Class<?> clazz, Long id) throws BusinessException {
		Assert.notNull(id, "[JPA] 参数id不能为空");
		try {
			BaseEntity<Long> entity = (BaseEntity<Long>) clazz.getDeclaredConstructor().newInstance();
			entity.setId(id);
			this.entityManager.remove(this.entityManager.contains(entity) ? entity : this.entityManager.merge(entity));
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	@SuppressWarnings("unchecked")
	public void delete(Class<?> clazz, Long[] ids) throws BusinessException {
		Assert.notEmpty(ids, "[JPA] 参数ids不能为空");
		try {
			for (int i = 0; i < ids.length; i++) {
				BaseEntity<Long> entity = (BaseEntity<Long>) clazz.getDeclaredConstructor().newInstance();
				entity.setId(ids[i]);
				this.entityManager.remove(this.entityManager.contains(entity) ? entity : this.entityManager.merge(entity));
			}
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	@SuppressWarnings("unchecked")
	public <T> T find(Class<?> clazz, Long id) throws BusinessException {
		Assert.notNull(id, "[JPA] 参数id不能为空");
		T t = null;
		try {
			t = (T) this.entityManager.find(clazz, id);
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return t;
	}

	@SuppressWarnings("unchecked")
	public void update(BaseEntity<Long> entity) throws BusinessException {
		try {
			BaseEntity<Long> baseEntity = this.find(entity.getClass(), entity.getId());
			baseEntity = (BaseEntity<Long>) DaoHelper.combineBean(entity, baseEntity);
			this.entityManager.merge(baseEntity);
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	public void updateAll(BaseEntity<Long> entity) throws BusinessException {
		try {
			if (!this.entityManager.contains(entity)) {
				this.entityManager.merge(entity);
			}
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
	}

	@SuppressWarnings("unchecked")
	public <T> T find(String hql, Class<?> clazz) throws BusinessException {
		T t = null;
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql, clazz);
			List<T> result = query.getResultList();
			Iterator<T> iterator = result.iterator();
			if (iterator.hasNext()) {
				t = iterator.next();
			}
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return t;
	}

	@SuppressWarnings("unchecked")
	public <T> T find(String hql, Object para, Class<?> clazz) throws BusinessException {
		T t = null;
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql, clazz);
			query.setParameter(0, para);
			List<T> result = query.getResultList();
			Iterator<T> iterator = result.iterator();
			if (iterator.hasNext()) {
				t = iterator.next();
			}
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return t;
	}

	@SuppressWarnings("unchecked")
	public <T> T find(String hql, List<Object> paras, Class<?> clazz) throws BusinessException {
		T t = null;
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql, clazz);
			DaoHelper.setQueryParas(query, paras);
			List<T> result = query.getResultList();
			Iterator<T> iterator = result.iterator();
			if (iterator.hasNext()) {
				t = iterator.next();
			}
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return t;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> search(String hql, Class<?> clazz, Page page) throws BusinessException {
		if(null == page){
			page = new Page();
			page.setPageNumber(DEFAULT_PAGE_NUM);
			page.setPageSize(DEFAULT_PAGE_SIZE);
		}
		page.setTotalRow(this.count(hql));
		List<T> list = null;
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql, clazz);
			query.setFirstResult(page.getFromIndex()).setMaxResults(page.getPageSize());
			list = query.getResultList();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> search(String hql, Object para, Class<?> clazz) throws BusinessException {
		List<T> list = null;
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql, clazz);
			query.setParameter(0, para);
			list = query.getResultList();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> search(String hql, List<Object> paras, Class<?> clazz, Page page) throws BusinessException {
		if(null == page){
			page = new Page();
			page.setPageNumber(DEFAULT_PAGE_NUM);
			page.setPageSize(DEFAULT_PAGE_SIZE);
		}
		page.setTotalRow(this.count(hql, paras));
		List<T> list = null;
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql, clazz);
			DaoHelper.setQueryParas(query, paras);
			query.setFirstResult(page.getFromIndex()).setMaxResults(page.getPageSize());
			list = query.getResultList();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> search(String hql, Class<?> clazz) throws BusinessException {
		List<T> list = null;
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql, clazz);
			list = query.getResultList();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> search(String hql, List<Object> paras, Class<?> clazz) throws BusinessException {
		List<T> list = null;
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			Query query = this.entityManager.createQuery(queryHql, clazz);
			DaoHelper.setQueryParas(query, paras);
			list = query.getResultList();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 执行HQL语句错误 ...", e);
		}
		return list;
	}

	public int count(String hql, List<Object> paras) throws BusinessException {
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			String queryCountHql = DaoHelper.getQueryCountHql(queryHql);
			Query query = this.entityManager.createQuery(queryCountHql);
			DaoHelper.setQueryParas(query, paras);
			return ((Long) query.getResultList().iterator().next()).intValue();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 数据统计总数错误 ...", e);
		}
	}

	public int count(String hql, Object para) throws BusinessException {
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			String queryCountHql = DaoHelper.getQueryCountHql(queryHql);
			Query query = this.entityManager.createQuery(queryCountHql);
			query.setParameter(0, para);
			return ((Long) query.getResultList().iterator().next()).intValue();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 数据统计总数错误 ...", e);
		}
	}

	public int count(String hql) throws BusinessException {
		try {
			String queryHql = DaoHelper.getQueryHql(hql);
			String queryCountHql = DaoHelper.getQueryCountHql(queryHql);
			Query query = this.entityManager.createQuery(queryCountHql);
			return ((Long) query.getResultList().iterator().next()).intValue();
		} catch (Exception e) {
			throw new BusinessException("[JPA] 数据统计总数错误 ...", e);
		}
	}

}
